package com.ourteam.frame.controller;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.ourteam.frame.web.AbstractTreeBuilder;
import com.ourteam.frame.web.TreeParamModel;
import com.ourteam.frame.web.TreeViewNodeBean;

public abstract class AbstractTreeBuilderController<T extends AbstractTreeBuilder> extends AbstractServiceController {
	
	/**
	 * Logger for this class
	 */
	private static final Log logger = LogFactory.getLog(AbstractTreeBuilderController.class);

	public static final int ALL_LEVEL = -1;

	public static final int ROOT_LEVEL = 0;

	abstract protected T getTreeBuilder(HttpServletRequest request)  throws Exception;

	abstract protected Object getInitParameter(HttpServletRequest request);

	@RequestMapping("/buildTree")
	@CrossOrigin
	@ResponseBody
	public List<TreeViewNodeBean> buildTree(@ModelAttribute TreeParamModel treeParamModel,
			@RequestParam(defaultValue = "0") int expandLevel, @RequestParam(required = false) String selectedNodeId,
			@RequestParam(required = true) String requestId, HttpServletRequest request) throws Exception {
		
		T treeBuilder = null;

		if (treeParamModel.isFinished()) {
			logger.debug("Finish Tree Build " + requestId);
			request.getSession().removeAttribute(requestId);
			return new ArrayList<TreeViewNodeBean>();
		}

		int nodeLevel = 0;
		
		Object obj = request.getSession().getAttribute(requestId);
		
		if(obj == null){
			treeBuilder = getTreeBuilder(request);
			request.getSession().setAttribute(requestId, treeBuilder);
		}
		else{
			treeBuilder = (T)obj;
		}

		if (StringUtils.isNotEmpty(treeParamModel.getN_level())) {
			nodeLevel = Integer.parseInt(treeParamModel.getN_level());
		}

		String parentObj = treeParamModel.getNodeid();

		if (parentObj == null && getInitParameter(request) != null) {
			parentObj = String.valueOf(getInitParameter(request));
		}

		List<TreeViewNodeBean> treeViewNodeBeans = new ArrayList<TreeViewNodeBean>();

		buildTreeNode(treeBuilder,parentObj, nodeLevel, treeParamModel.getNodeConfigId(), treeViewNodeBeans, expandLevel,
				selectedNodeId, request);

		return treeViewNodeBeans;
	}

	protected void buildTreeNode(T treeBuilder, Object parentObj, int level, String nodeCinfigId, List<TreeViewNodeBean> treeNodes,
			int expandLevel, String selectedNodeId, HttpServletRequest request) throws Exception {

		if (parentObj == null && getInitParameter(request) != null) {
			parentObj = String.valueOf(getInitParameter(request));
		}

		TreeViewNodeBean[] treeViewNodeBeans = treeBuilder.getTreeGrid(parentObj, level, nodeCinfigId);

		for (int i = 0; i < treeViewNodeBeans.length; i++) {

			TreeViewNodeBean treeViewNodeBean = treeViewNodeBeans[i];

			if (treeViewNodeBean.getId().equals(selectedNodeId)) {
				treeViewNodeBean.getState().setSelected(true);
			}

			treeNodes.add(treeViewNodeBean);
			
			if ((expandLevel != ALL_LEVEL && level < expandLevel && treeViewNodeBean.getIsLeaf() == false)
					|| (expandLevel == ALL_LEVEL && treeViewNodeBean.getIsLeaf() == false)) {
//				buildTreeNode(treeBuilder,treeViewNodeBean.getId(), level + 1, treeViewNodeBean.getNodeConfigId(), treeViewNodeBean,
//						expandLevel,selectedNodeId,request);

				treeViewNodeBean.getState().setExpanded(true);
			} else {
				treeViewNodeBean.getState().setExpanded(false);
			}

		}

	}

}
